package com.buddha.api.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.buddha.api.common.Constants;
import com.buddha.api.common.Result;
import com.buddha.api.entity.Role;
import com.buddha.api.entity.RoleMenu;
import com.buddha.api.entity.UserRole;
import com.buddha.api.service.impl.RoleMenuServiceImpl;
import com.buddha.api.service.impl.RoleServiceImpl;
import com.buddha.api.service.impl.UserRoleServiceImpl;
import com.buddha.api.service.impl.UserServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author mybatis-plus
 * @since 2023-07-06
 */
@CrossOrigin(origins = {"*"})
@RestController
@RequestMapping("/role")
public class RoleController {

    @Autowired
    private RoleServiceImpl roleService;

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private UserRoleServiceImpl userRoleService;

    @Autowired
    private RoleMenuServiceImpl roleMenuService;

    @PreAuthorize("hasAuthority('sys:role:save')")
    @PostMapping("/save")
    public Result saveRole(@RequestBody Role role){
        role.setCreated(LocalDateTime.now());
        role.setState(Constants.STATE_ON);
        return Result.success(roleService.save(role));
    }

    @PreAuthorize("hasAuthority('sys:role:update')")
    @PostMapping("/update")
    public Result updateRole(@RequestBody Role role){
        role.setUpdated(LocalDateTime.now());
        userService.clearUserAuthorityByRole(role.getId());
        return Result.success(roleService.updateById(role));
    }

    @PreAuthorize("hasAuthority('sys:role:delete')")
    @PostMapping("/delete")
    @Transactional
    public Result deletesRole(@RequestBody Integer[] ids){
        roleService.removeByIds(Arrays.asList(ids));
        for (int id : ids) {
            userService.clearUserAuthorityByRole(id);
            userRoleService.remove(new QueryWrapper<UserRole>().eq("r_id",id));
            roleMenuService.remove(new QueryWrapper<RoleMenu>().eq("r_id",id));
        }
        return Result.success();
    }

    @PreAuthorize("hasAuthority('sys:role:perm')")
    @PostMapping("/perm/{roleId}")
    public Result allocatePermission(@PathVariable("roleId") Integer roleId, @RequestBody Integer[] menuIds){
        List<RoleMenu> roleMenuList = new ArrayList<>();
        for (int menuId : menuIds) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setMId((int) menuId);
            roleMenu.setRId((int) roleId);
            roleMenuList.add(roleMenu);
        }
        roleMenuService.remove(new QueryWrapper<RoleMenu>().eq("r_id",roleId));
        roleMenuService.saveBatch(roleMenuList);
        userService.clearUserAuthorityByRole(roleId);
        return Result.success();
    }


    @PreAuthorize("hasAuthority('sys:role:list')")
    @GetMapping
    public Result findAll() {
        return Result.success(roleService.list());
    }

    @PreAuthorize("hasAuthority('sys:role:list')")
    @GetMapping("/{id}")
    public Result findOne(@PathVariable Integer id) {
        Role role = roleService.getById(id);
        List<Integer> mIds = roleMenuService.list(new QueryWrapper<RoleMenu>().eq("r_id", id)).stream().map(r -> r.getMId()).collect(Collectors.toList());
        role.setMenuIds(mIds);
        return Result.success(role);
    }

    @PreAuthorize("hasAuthority('sys:role:list')")
    @GetMapping("/page")
    public Result findPage(
            @RequestParam Integer pageNum,
            @RequestParam Integer pageSize,
            @RequestParam(defaultValue = "") String name) {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("name",name);
        return Result.success(roleService.page(new Page<>(pageNum, pageSize),queryWrapper));
    }

}